/********************************************************************
        created:        2010/02/21
        filename:       htl_epoll.cpp
        author:         HongLiang

        purpose:        epoll
*********************************************************************/
#ifndef __HTL_EPOLL_CPP__
#define __HTL_EPOLL_CPP__
#include <cstring>
#include "htl_io_event.h"
#include "htl_epoll.h"
#include "../container/htl_config.h"
__HTL_BEGIN_NAMESPACE

HTL_RESULT epoll_aux::event_init(int _maxfds) {
	maxfds = _maxfds;
	/*epoll_events = new epoll_event[maxfds];
	sequence_hander = new call_hander[maxfds]; */
	epoll_events.reserve(maxfds);
	sequence_handler.reserve(maxfds);
	epoll_fd = epoll_create(maxfds);
	if (-1 == epoll_fd)
		return HTL_ERROR;
	return HTL_SUCCESS;
}

HTL_RESULT epoll_aux::event_add(int fd, int events) {
	epoll_event ep;
	memset(&ep, 0x0, sizeof(ep));
	if (events & FDEVENT_IN) ep.events |= EPOLLIN | EPOLLET;
	if (events & FDEVENT_OUT) ep.events |= EPOLLOUT | EPOLLET;
	ep.data.ptr = NULL;
	ep.data.fd = fd;
	if (0 != epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ep)) 
		return HTL_ERROR;
	return HTL_SUCCESS;
}

HTL_RESULT epoll_aux::event_mod(int fd, int events) {
	epoll_event ep;
	memset(&ep, 0x0, sizeof(ep));
	if (events & FDEVENT_IN) ep.events |= EPOLLIN | EPOLLET;
	if (events & FDEVENT_OUT) ep.events |= EPOLLOUT | EPOLLET;
	ep.data.ptr = NULL;
	ep.data.fd = fd;
	if (0 != epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ep))
		return HTL_ERROR;
	return HTL_SUCCESS;
}

HTL_RESULT epoll_aux::event_del(int fd) {
	epoll_event ep;
	memset(&ep, 0x0, sizeof(ep));
	ep.data.fd = fd;
	ep.data.ptr = NULL;
	if (0 != epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &ep))
		return HTL_ERROR;
	return HTL_SUCCESS;
}

HTL_RESULT epoll_aux::event_register(int fd, call_handler handler) {
	sequence_handler[fd] = handler;
	return HTL_SUCCESS;
}

HTL_RESULT epoll_aux::event_unregister(int fd) { 
	if (sequence_handler[fd]) {
		sequence_handler[fd] = NULL; 
		return HTL_SUCCESS;
	} else 
		return HTL_ERROR;
}

HTL_RESULT epoll_aux::event_poll(void* args, int timeout_ms) {
	int nfds = 0;
	int i = 0;
	for (; ; ) {
		//if ((nfds = epoll_wait(epoll_fd, epoll_events, maxfds, timeout_ms))> 0) {
		if ((nfds = epoll_wait(epoll_fd, epoll_events.begin(), maxfds, timeout_ms))> 0) {
			for (i = 0; i < nfds; ++i) {
				int events = 0, e;
				call_handler handler = NULL;
				e = epoll_events[i].events;
				if (e & EPOLLIN) events |= FDEVENT_IN;
				if (e & EPOLLOUT) events |= FDEVENT_OUT;
				// call back
				handler = sequence_handler[epoll_events[i].data.fd];
				(*handler)(this, epoll_events[i].data.fd, events, args);
			}
		}
	}
}

__HTL_END_NAMESPACE
#endif

